/*小车驱动代码
采用的tb6612驱动，你记得注意电压一定给够，还有共地；

https://blog.csdn.net/qq_45217381/article/details/131813114
https://blog.51cto.com/u_14114084/5247993
https://www.bilibili.com/read/cv26112416/
tb6612的文章你看下，就能懂上面的引脚都是干嘛的，不懂就问

https://gitee.com/HiSpark/hi3861_hdu_iot_application/raw/master/src/vendor/bearpi/bearpi_hm_nano/doc/board/BearPi_HM%20Nano%20%E8%8A%AF%E7%89%87%E6%89%8B%E5%86%8C.pdf
芯片手册，就能懂上面的引脚都是干嘛的，不懂就问

在这直接用了，但在这没定义的函数，都是官方封装好了的，包含头文件就可以直接用，不懂这个函数干嘛的，你就复制百度搜或者问gpt
这里每个实验的接口说明都有函数解释
https://gitee.com/HiSpark/hi3861_hdu_iot_application/blob/master/doc/%E7%89%A9%E8%81%94%E7%BD%91%E6%8A%80%E6%9C%AF%E5%8F%8A%E5%BA%94%E7%94%A8%E5%AE%9E%E9%AA%8C%E6%8C%87%E5%AF%BC%E6%89%8B%E5%86%8C.md#3631-iotpwminit

#接线
vm---12v                 PWMA---GPIO2
vcc---5V/3.3V            AIN2---GPIO1
GND---GND                AIN1---GPIO0
AO1---左电机红            STBY---5V/3.3V
AO2---左电机白            BIN1---GPIO6
BO2---右电机白            BIN2---GPIO7
BO1---右电机红            PWMB---GPIO5
GND---不接                GND---不接

#如果电机转动是反的，要么改代码，要么换接线，跟现在的反着来就行
*/

// 这几个头文件在同级目录下的build.gn里面有指定位置，可以去验证一下他们在不在
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "iot_gpio_ex.h"
#include "iot_gpio.h"
#include "iot_gpio_ex.h"
#include "iot_pwm.h"
#include "ohos_init.h"
#include "iot_errno.h"
#include "iot_uart.h"


// #include "iot_i2c.h"
// #include "nfc.h"

// 这个记得去了解一下哦
#define THREAD_STACK_SIZE (1024 * 6) // 线程的栈大小
#define THREAD_PRIO 25               // 线程优先级

#if 1
// 定义要用的gpio口
#define PWM1_GPIO 2
#define L1_GPIO 0
#define L2_GPIO 1

#define PWM2_GPIO 5
#define N1_GPIO 6
#define N2_GPIO 7

// 定义与循迹传感器连接的GPIO引脚
#define SENSOR_L1 8  // 2
#define SENSOR_M 9   // 3
#define SENSOR_R1 10 // 4

#define DishDetector 3
#define R 12
#define T 11
#else
// 定义要用的gpio口
#define L1_GPIO WIFI_IOT_IO_NAME_GPIO_0
#define L2_GPIO WIFI_IOT_IO_NAME_GPIO_1

#define N1_GPIO WIFI_IOT_IO_NAME_GPIO_6
#define N2_GPIO WIFI_IOT_IO_NAME_GPIO_7

// 定义与循迹传感器连接的GPIO引脚
#define SENSOR_L1 WIFI_IOT_IO_NAME_GPIO_8  // 2
#define SENSOR_M WIFI_IOT_IO_NAME_GPIO_9   // 3
#define SENSOR_R1 WIFI_IOT_IO_NAME_GPIO_10 // 4

#define DishDetector WIFI_IOT_IO_NAME_GPIO_3
#define PWM1_GPIO HI_PWM_PORT_PWM1
#define PWM2_GPIO HI_PWM_PORT_PWM2
#endif

#if 1
#else
#define IOT_GPIO_FUNC_GPIO_8_GPIO WIFI_IOT_IO_FUNC_GPIO_8_GPIO
#define IOT_GPIO_FUNC_GPIO_9_GPIO WIFI_IOT_IO_FUNC_GPIO_9_GPIO
#define IOT_GPIO_FUNC_GPIO_10_GPIO WIFI_IOT_IO_FUNC_GPIO_10_GPIO
#define IOT_GPIO_FUNC_GPIO_11_GPIO WIFI_IOT_IO_FUNC_GPIO_11_GPIO
#define IOT_GPIO_FUNC_GPIO_2_PWM2_OUT WIFI_IOT_IO_FUNC_GPIO_2_PWM2_OUT
#define IOT_GPIO_FUNC_GPIO_5_PWM2_OUT WIFI_IOT_IO_FUNC_GPIO_5_PWM2_OUT
#define IoTGpioSetDir GpioSetDir
#define IOT_GPIO_DIR_OUT WIFI_IOT_GPIO_DIR_OUT
#define IoTPwmInit hi_pwm_init
#define IoTGpioSetFunc IoSetFunc
#define IOT_GPIO_DIR_IN WIFI_IOT_GPIO_DIR_IN
#define IoTPwmStart hi_pwm_start
#define IoTGpioSetOutputVal GpioSetOutputVal
#define IotGpioValue WifiIotGpioValue
#define IoTGpioGetInputVal GpioGetInputVal
#define IotUartAttribute WifiIotUartAttribute
#define IOT_SUCCESS HI_ERR_SUCCESS
#define IoTUartRead hi_uart_read

#endif

// 这两个值干嘛的，有什么用，去理解pwm，懂频率，占空比，预分频系数，pwm是个啥。很简单的，沉淀半个小时你就会了，然后自己来调一调速度
#define IOT_FREQ 65535 // 频率
#define IOT_DUTY 70    // 占空比

// GPIO Value
#define white (int)0
#define black (int)1
#define plateEmpty (int)0
// //时钟
// #define PWM_CHANGE_TIMES 100
// #define PWM_FREQ 40000
// #define PWM_DELAY_10US 10

// UART config
#define UART_TASK_STACK_SIZE (1024 * 8)
#define UART_TASK_PRIO 25
#define UART_BUFF_SIZE 1000
#define WIFI_IOT_UART_IDX_1 1
#define TASK_DELAY_1S 1000000

static const char *data = "Ready";


// I2C NFC config
// #define I2C_TASK_STACK_SIZE (1024 * 8)
// #define I2C_TASK_PRIO 25
// #define WIFI_IOT_IO_FUNC_GPIO_0_I2C1_SDA 6
// #define WIFI_IOT_IO_FUNC_GPIO_1_I2C1_SCL 6
// #define WIFI_IOT_I2C_IDX 1
// #define WIFI_IOT_I2C_BAUDRATE 400000

int reverse = 0; // 返回开关
// static char ready[10] = "ready\r\n";
// 初始化函数
#if 1
void GpioInit_WIN32(void)
{
    // 初始化用到的GPIO口
    IoTGpioInit(PWM1_GPIO);
    IoTGpioInit(PWM2_GPIO);
    IoTGpioInit(L1_GPIO);
    IoTGpioInit(L2_GPIO);
    IoTGpioInit(N1_GPIO);
    IoTGpioInit(N2_GPIO);

    // 初始化循迹传感器GPIO引脚
    IoTGpioInit(SENSOR_L1);
    IoTGpioInit(SENSOR_M);
    IoTGpioInit(SENSOR_R1);

    // 初始化盘子传感器GPIO引脚
    IoTGpioInit(DishDetector);
    IoTGpioInit(T);
    IoTGpioInit(R);
    IoTGpioSetFunc(R, IOT_GPIO_FUNC_GPIO_12_UART2_RXD);
    IoTGpioSetFunc(T, IOT_GPIO_FUNC_GPIO_11_UART2_TXD);
}
#endif

void Gpio_Init(void)
{
    // 复用gpio2和5为pwm，这个pwm通道2，是根据手册来的，我发群里，记得每个gpio口pwm通道不一样，看手册
    IoTGpioSetFunc(SENSOR_L1, IOT_GPIO_FUNC_GPIO_8_GPIO);
    IoTGpioSetFunc(SENSOR_M, IOT_GPIO_FUNC_GPIO_9_GPIO);
    IoTGpioSetFunc(SENSOR_R1, IOT_GPIO_FUNC_GPIO_10_GPIO);

    IoTGpioSetFunc(PWM1_GPIO, IOT_GPIO_FUNC_GPIO_2_PWM2_OUT);
    IoTGpioSetFunc(PWM2_GPIO, IOT_GPIO_FUNC_GPIO_5_PWM2_OUT);

    // 设置盘子传感器GPIO
    IoTGpioSetFunc(DishDetector, IOT_GPIO_FUNC_GPIO_3_GPIO);

    printf("finish GPIO SetFunc\r\n");

    // 全部设置为输出模式，可以理解为能够输出高低两种电平
    IoTGpioSetDir(PWM1_GPIO, IOT_GPIO_DIR_OUT);
    IoTGpioSetDir(L1_GPIO, IOT_GPIO_DIR_OUT);
    IoTGpioSetDir(L2_GPIO, IOT_GPIO_DIR_OUT);
    IoTGpioSetDir(PWM2_GPIO, IOT_GPIO_DIR_OUT);
    IoTGpioSetDir(N1_GPIO, IOT_GPIO_DIR_OUT);
    IoTGpioSetDir(N2_GPIO, IOT_GPIO_DIR_OUT);

    // 设置循迹模块为输入模式
    IoTGpioSetDir(SENSOR_L1, IOT_GPIO_DIR_IN);
    IoTGpioSetDir(SENSOR_M, IOT_GPIO_DIR_IN);
    IoTGpioSetDir(SENSOR_R1, IOT_GPIO_DIR_IN);

    // 设置循迹模块为输入模式
    IoTGpioSetDir(DishDetector, IOT_GPIO_DIR_IN);

    printf("finish GPIO SetDir\r\n");

    // 初始化指定PWM
    IoTPwmInit(PWM1_GPIO);
    IoTPwmInit(PWM2_GPIO);
    printf("finish PWN Init\r\n");

    // 启动pwm
    // hi_pwm_set_clock(PWM_CLK_160M);
    // hi_pwm_set_clock(PWM_CLK_160M);
    IoTPwmStart(PWM1_GPIO, IOT_DUTY, IOT_FREQ);
    IoTPwmStart(PWM2_GPIO, IOT_DUTY, IOT_FREQ);
    printf("Start PWM OK\r\n");
}

// 前进
void Advance(void)
{
    IoTGpioSetOutputVal(L1_GPIO, 0); // 1：高电平  0：低电平   下面的同理
    IoTGpioSetOutputVal(L2_GPIO, 1);
    IoTGpioSetOutputVal(N1_GPIO, 0);
    IoTGpioSetOutputVal(N2_GPIO, 1);
    printf("Advance\r\n");
}

// 后退
void Backward(void)
{
    IoTGpioSetOutputVal(L1_GPIO, 1);
    IoTGpioSetOutputVal(L2_GPIO, 0);
    IoTGpioSetOutputVal(N1_GPIO, 1);
    IoTGpioSetOutputVal(N2_GPIO, 0);
    printf("Back\r\n");
}

// 左转
void Turnleft(void)
{
    if (reverse == 0)
    {
        IoTGpioSetOutputVal(L1_GPIO, 0);
        IoTGpioSetOutputVal(L2_GPIO, 0);
        IoTGpioSetOutputVal(N1_GPIO, 0);
        IoTGpioSetOutputVal(N2_GPIO, 1);
        printf("Turnleft\r\n");
    }
    else
    {
        IoTGpioSetOutputVal(L1_GPIO, 0);
        IoTGpioSetOutputVal(L2_GPIO, 1);
        IoTGpioSetOutputVal(N1_GPIO, 0);
        IoTGpioSetOutputVal(N2_GPIO, 0);
        printf("Turnright\r\n");
    }
}

// 掉头
void Turnaround(void)
{
    IoTGpioSetOutputVal(L1_GPIO, 1);
    IoTGpioSetOutputVal(L2_GPIO, 0);
    IoTGpioSetOutputVal(N1_GPIO, 0);
    IoTGpioSetOutputVal(N2_GPIO, 1);
    printf("Turnaround\r\n");
}

// 右转
void Turnright(void)
{
    if (reverse == 0)
    {
        IoTGpioSetOutputVal(L1_GPIO, 0);
        IoTGpioSetOutputVal(L2_GPIO, 1);
        IoTGpioSetOutputVal(N1_GPIO, 0);
        IoTGpioSetOutputVal(N2_GPIO, 0);
        printf("Turnright\r\n");
    }
    else
    {
        IoTGpioSetOutputVal(L1_GPIO, 0);
        IoTGpioSetOutputVal(L2_GPIO, 0);
        IoTGpioSetOutputVal(N1_GPIO, 0);
        IoTGpioSetOutputVal(N2_GPIO, 1);
        printf("Turnleft\r\n");
    }
}

// 停止
void Stop(void)
{
    IoTGpioSetOutputVal(L1_GPIO, 0);
    IoTGpioSetOutputVal(L2_GPIO, 0);
    IoTGpioSetOutputVal(N1_GPIO, 0);
    IoTGpioSetOutputVal(N2_GPIO, 0);
    printf("Stop\r\n");
}

// 巡线
IotGpioValue ValueL1, ValueM, ValueR1, DishStatus;
void FindWay(void)
{
    IoTGpioGetInputVal(SENSOR_L1, &ValueL1);
    IoTGpioGetInputVal(SENSOR_M, &ValueM);
    IoTGpioGetInputVal(SENSOR_R1, &ValueR1);
    // printf("%d %d %d", ValueL1, ValueM, ValueR1);

    if (ValueL1 == white && ValueR1 == black)
    {
        Turnright();
    }
    if (ValueL1 == black && ValueR1 == white)
    {
        Turnleft();
    }
    if (ValueL1 == white && ValueR1 == white)
    {
        if (ValueM == black)
        {
            Advance();
        }
        else
        {
            Stop();
        }
    }
}

int compchar(char *p1, char *p2)
{
    int res = 0;                                   // 初始res = 0
    for (; *p1 != '\0' || *p2 != '\0'; p1++, p2++) // 将两个字符串的每一元素进行比较
    {
        if (*p1 != *p2) // 出现第一个不相等元素时
        {
            res = *p1 - *p2; // res的值改变，为两个字母ASCLL相减的值
            break;           // 中止循环
        }
    }
    return res; // 如果两个字符串全部相等，则不进入循环，最终返回值res不变仍为0.
}

// 主函数
static void PwmTask(void)
{
/* ----INIT---- */
#if 1
    GpioInit_WIN32(); // 调用初始化
#else
    GpioInit();
#endif
    printf("finish GPIO Init\r\n");
    Gpio_Init();
    // UART
    uint8_t uart_buff[UART_BUFF_SIZE] = {0};
    unsigned char uartReadBuff[UART_BUFF_SIZE] = {0};
    uint32_t ret;
    /* RT->TX
     * TX->RX
     */
    IotUartAttribute uart_attr = {

        // baud_rate: 9600
        .baudRate = 9600,

        // data_bits: 8bits
        .dataBits = 8,
        .stopBits = 1,
        .parity = 0,
    };

// Initialize uart driver
#if 1
    ret = IoTUartInit(WIFI_IOT_UART_IDX_1, &uart_attr);
#else
    ret = UartInit(WIFI_IOT_UART_IDX_1, &uart_attr, HI_NULL);
#endif
    if (ret != IOT_SUCCESS)
    {
        printf("Failed to init uart! Err code = %d\r\n", ret);
        return;
    }


    printf("Init uart ok\r\n");
    /* ----INIT finish---- */
 int readBuffLen=0;
    IoTGpioGetInputVal(DishDetector, &DishStatus);
    printf("plate is %d\r\n", DishStatus);

    while (DishStatus != plateEmpty && compchar(uartReadBuff, "Ready") == 0)
    {
        IoTGpioGetInputVal(DishDetector, &DishStatus);
        // receive data through uart1
       
        readBuffLen = IoTUartRead(WIFI_IOT_UART_IDX_1, uartReadBuff, UART_BUFF_SIZE);
        printf("Uart1 read data:%s,lenth%d\r\n", uartReadBuff,readBuffLen);
        printf("plate is %d\r\n", &DishStatus);
    }
    printf("plate is ready\r\n");
    usleep(TASK_DELAY_1S);
    printf("GO\r\n");
    while (1)
    {
    }
    FindWay();
    Turnaround();
    reverse = 1;
    FindWay();
}

static void PwmExampleEntry(void)
{
    osThreadAttr_t attr;
    attr.name = "PwmTask"; // 这里说一下，改主函数入口，就改这个参数，跟主函数名对应
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = THREAD_STACK_SIZE;
    attr.priority = THREAD_PRIO;
    if (osThreadNew((osThreadFunc_t)PwmTask, NULL, &attr) == NULL)
    {
        printf("Failed to create PwmTask!\n");
    }
}

APP_FEATURE_INIT(PwmExampleEntry); // 启动应用层功能

// 大胆去试，多用百度，不懂就问，不要怕错，多动手，大不了板子烧了让你姐再给你买，加油
